package com.yc.Testjvm.invoke;

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;

public class MethodHandleTeast {

	static class ClassA {
		public void println(String s) {
			System.out.println(s);
		}
	}
	
	public static void main(String[] args) throws Throwable {
		Object obj = System.currentTimeMillis() % 2 == 0 ? System.out : new ClassA();
		//无论obj最终是哪个实现类，下面这句话都能正确调到println方法
		getPrintlnMH(obj).invokeExact("abc");
	}
	
	private static MethodHandle getPrintlnMH(Object reveiver) throws Throwable {
		//MethodType：代表“方法类型”，包含了方法的返回值（methodType的第一个参数），具体参数（methodType的第二个参数及以后的参数）
		MethodType mt = MethodType.methodType(void.class, String.class);
		//MethodHandles.lookup()的作用是：在指定类中查找符合给定方法名，方法类型，并符合调用权限的的方法句柄
		//因为这里调用的是一个虚方法，按照java语言规则，方法的第一个参数是隐式的，代表该方法的接收者，也即是this指向的对象，
		//这个参数以前是放在参数列表中进行传递的，而现在提供了bindTo()方法来完成这件事
		return MethodHandles.lookup().findVirtual(reveiver.getClass(), "println", mt).bindTo(reveiver);
		
	}
}
